﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using SpaceShooter.Extensions;
using System.Diagnostics;
using SpaceShooter.Common;

namespace SpaceShooter.Components
{
    public static class CollisionManager
    {
        private static IList<GameObject> allCollisionObjects = new List<GameObject>();

        public static void AddObject(GameObject o)
        {
            allCollisionObjects.Add(o);
        }

        public static void AddObject(IEnumerable<GameObject> list)
        {
            foreach (var item in list)
            {
                allCollisionObjects.Add(item);
            }
        }

        public static void RemoveObject(GameObject o)
        {
            allCollisionObjects.Remove(o);
        }

        public static void RemoveObject(IEnumerable<GameObject> list)
        {
            foreach (var item in list)
            {
                allCollisionObjects.Remove(item);
            }
        }

        public static void PerformCollisionDetection(Action<GameObject> collisionReporter)
        {
            bool collided = false;

            for (int i = allCollisionObjects.Count - 1; i >= 0; i--)
            {
                var bs1 = allCollisionObjects[i].GetBoundingSphere();
                var collider1 = allCollisionObjects[i];

                for (int j = allCollisionObjects.Count - 1; j >= 0; j--)
                {
                    if (i == j)
                        continue;

                    if (allCollisionObjects[i] == allCollisionObjects[j])
                        continue;

                    var bs2 = allCollisionObjects[j].GetBoundingSphere();
                    var collider2 = allCollisionObjects[j];

                    if (bs1.Intersects(bs2))
                    {
                        if (!collider1.RemoveFlag  && !collider2.RemoveFlag)
                        {
                            collider2.ApplyDamage(collider1);
                            collider1.ApplyDamage(collider2);
                            collided = true;

                            if (collider1.RemoveFlag)
                            {
                                SpreadExplosionDamage(collider1.DamageOnExplosion, collider1.Position);
                            }

                            if (collider2.RemoveFlag)
                            {
                                SpreadExplosionDamage(collider2.DamageOnExplosion, collider2.Position);
                            }
                        }
                    }
                }
            }

            if (collided)
            {
                allCollisionObjects.RemoveMarkedObjected(collisionReporter);
            }
        }

        private static void SpreadExplosionDamage(float damagePoints, Vector3 position)
        {
            float damageRadius = (float)Math.Pow(damagePoints * 30000000.0, 1.0/3.0);

            var damageSphere = new BoundingSphere(position, damageRadius);

            Debug.WriteLine(damageRadius);

            var allColliders = new List<GameObject>();

            for (int i = allCollisionObjects.Count - 1; i >= 0; i--)
            {
                var collider = allCollisionObjects[i];

                if (collider.RemoveFlag)
                    continue;

                if (collider.GetBoundingSphere().Intersects(damageSphere))
                {
                    allColliders.Add(collider);
                }
            }

            if (allColliders.Count == 0)
                return;

            float damagePerObject = damagePoints / allColliders.Count;

            allColliders.ForEach(o =>
                {
                    o.ApplyDamage(damagePerObject);
                    if (o.RemoveFlag)
                        SpreadExplosionDamage(o.DamageOnExplosion, o.Position);
                });
        }

        [Obsolete]
        private static void hitAction(GameObject o1, GameObject o2)
        {
        }

        [Obsolete]
        public static void CollisionDetection(IList<GameObject> list1, IList<GameObject> list2, Action<GameObject, GameObject> hitAction)
        {
            for (int i = list1.Count - 1; i >= 0; i--)
            {
                var bs1 = list1[i].GetBoundingSphere();

                for (int j = list2.Count - 1; j >= 0; j--)
                {
                    var bs2 = list2[j].GetBoundingSphere();

                    if (bs1.Intersects(bs2))
                    {
                        hitAction(list1[i], list2[j]);
                        list1.RemoveAt(i);
                        list2.RemoveAt(j);
                    }
                }
            }
        }

        [Obsolete]
        public static bool CollisionDetection(GameObject o, IList<GameObject> list2)
        {
            var bs1 = o.GetBoundingSphere();

            for (int j = list2.Count - 1; j >= 0; j--)
            {
                var bs2 = list2[j].GetBoundingSphere();

                if (bs1.Intersects(bs2))
                {
                    list2.RemoveAt(j);
                    return true;
                }
            }

            return false;
        }
    }
}
